package com.atldy.commerce.async.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.atldy.commerce.async.AsyncService;
import com.atldy.commerce.commence.goods.GoodsInfo;
import com.atldy.commerce.commence.goods.SimpleGoodsInfo;
import com.atldy.commerce.constant.GoodsConstant;
import com.atldy.commerce.enums.BrandCategory;
import com.atldy.commerce.enums.GoodsCategory;
import com.atldy.commerce.mapper.GoodsMapper;
import com.atldy.commerce.pojo.Goods;
import com.atldy.commerce.utlis.RedisUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.StopWatch;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @version 1.0
 * @Author: lidongyang
 * @CreateTime: 2021-08-18 20:53
 * @Description： 异步任务接口实现
 */
@Service
@Slf4j
public class AsyncServiceImpl implements AsyncService {

    @Autowired
    private GoodsMapper goodsMapper;

    @Autowired
    private RedisUtils redisUtils;

    /**
     * @author: 唐多令
     * @date: 2021/8/18 22:24
     * @param: [goodsInfos, taskId]
     * @description: 异步存储商品信息
     */
    @Async("getAsyncExecutor")
    @Override
    public void asyncAddGoodsInfo(List<GoodsInfo> goodsInfos, String taskId) {

        log.info("async task info [{}] taskId {}", JSONUtil.formatJsonStr(JSONUtil.toJsonStr(goodsInfos)), taskId);

        //计时
        StopWatch stopWatch = StopWatch.createStarted();

        //如果是goodsInfos中存在重复地商品信息不保存记录错误肉质

        boolean isIllegal = false;

        //讲商品信息字段joint在一起，用来判断是否有重复
        Set<String> jointGoodsInfos = new HashSet<>(goodsInfos.size());
        //过滤出来的可以入库的商品信息
        List<GoodsInfo> filteredGoodInfo = new ArrayList<>(goodsInfos.size());

        //过一遍循环，过滤非法参数与请求不合格的
        for (GoodsInfo goodsInfo : goodsInfos) {
            if (goodsInfo.getPrice() <= 0 || goodsInfo.getSupply() <= 0) {
                log.info("参数不合法:[{}]", JSONUtil.formatJsonStr(JSONUtil.toJsonStr(goodsInfo)));
                continue;
            }
            //组合商品信息
            String jointJson = String.format(
                    "%s,%s,%s", goodsInfo.getGoodsCategory(), goodsInfo.getBrandCategory()
                    , goodsInfo.getGoodsName()
            );
            log.info("组合商品信息 [{}]", jointJson);
            //是否存在重复商品信息
            if (jointGoodsInfos.contains(jointJson)) {
                isIllegal = true;
            }
            jointGoodsInfos.add(jointJson);
            filteredGoodInfo.add(goodsInfo);
        }

        //如果有重复不进行入库操作
        if (isIllegal || CollectionUtil.isEmpty(filteredGoodInfo)) {
            stopWatch.stop();
            log.info("商品信息重复,消耗时间：[{}]", stopWatch.getTime(TimeUnit.MICROSECONDS));
            return;
        }

        List<Goods> goodsList =
                filteredGoodInfo.stream().map(Goods::toGoods).collect(Collectors.toList());
        List<Goods> targetGoods = new ArrayList<>(goodsList.size());

        //保存商品之前在去判断和数据库中是否存在重复商品
        goodsList.stream().forEach(
                goods -> {
                    Goods categoryAndName =
                            this.findGoodsByStatusAndCategoryAndName(goods.getBrandCategory(), goods.getGoodsCategory(), goods.getGoodsName());
                    if (null != categoryAndName) {
                        log.error("数据库已存在商品信息[{}]",
                                JSONUtil.formatJsonStr(JSONUtil.toJsonStr(categoryAndName)));
                        throw new RuntimeException("数据库已存在商品信息");
                    }
                    targetGoods.add(goods);
                }
        );

        List<Goods> saveGoods = new ArrayList<>(goodsList.size());

        //循环商品信息入库
        targetGoods.stream().forEach(goods -> {
            int insert = goodsMapper.insert(goods);
            if (insert == 1) {
                saveGoods.add(goods);
            }
        });

        //商品信息存入redis
        setGoodsInfoRedis(saveGoods);
    }

    /**
     * redis存取商品简要信息
     */
    private void setGoodsInfoRedis(List<Goods> saveGoods) {
        List<SimpleGoodsInfo> simpleGoodsInfos =
                saveGoods.stream().map(Goods::toSimple).collect(Collectors.toList());
        Map<String, Object> id2JsonObject = new HashMap<>(simpleGoodsInfos.size());
        simpleGoodsInfos.forEach(
                g -> id2JsonObject.put(g.getId().toString(),JSON.toJSONString(g))
        );
        redisUtils.hmset(GoodsConstant.ECOMMERCE_GOODS_DICT_KEY, id2JsonObject);
    }

    Goods findGoodsByStatusAndCategoryAndName(BrandCategory brandCategory,
                                              GoodsCategory goodsCategory,
                                              String name) {
        if (brandCategory == null || goodsCategory == null || StrUtil.isBlank(name)) {
            log.error("请求参数不合法");
        }
        Goods goods = new Goods();
        goods.setGoodsCategory(goodsCategory);
        goods.setGoodsName(name);
        goods.setBrandCategory(brandCategory);
        QueryWrapper<Goods> wrapper = new QueryWrapper<>(goods);
        goods = goodsMapper.selectOne(wrapper);
        return goods;
    }


}